package com.lcy.lambda.stream;

import cn.hutool.core.collection.CollectionUtil;
import com.lcy.lambda.data.Author;
import com.lcy.lambda.data.Book;

import java.util.*;
import java.util.stream.Collectors;


import static com.lcy.lambda.data.Author.getAuthors;

/**
 * 中间操作
 * filter ：可以对流中的元素进行条件过滤，符合过滤条件的才能继续留在流中
 * map：    可以把对流中的元素进行计算或转换
 * distinct: 去重（注意：distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以需要注意重写equals方法。）
 * sorted ：注意：如果调用空参的sorted()方法，需要流中的元素是实现了Comparable。
 * limit： 可以设置流的最大长度，超出的部分将被抛弃。
 * skip： 跳过流中的前n个元素，返回剩下的元素
 * flatMap： 可以把一个对象转换成多个对象作为流中的元素
 *
 * @author lcy
 * @date 2024/9/23 17:23
 */
public class 中间操作 {


    /**
     * 过滤操作用法
     */
    public void filter() {
        //打印所有姓名长度大于1的作家的姓名
        List<Author> authors = getAuthors();
        authors.stream().filter(author -> author.getName().length() > 1)
                .forEach(author -> System.out.println(author.getName()));
    }

    /**
     * 去重操作
     */
    public void distinct() {
        //打印所有作家的姓名，并且要求其中不能有重复元素。
        List<Author> authors = getAuthors();
        authors.stream().distinct().forEach(author -> System.out.println(author.getName()));
    }


    /**
     * 注意：如果调用空参的sorted()方法，需要流中的元素是实现了Comparable。
     * 排序
     */
    public void sorted() {
        //对流中的元素按照年龄进行降序排序，并且要求不能有重复的元素。
        List<Author> authors = getAuthors();
        authors.stream().distinct().sorted((author1,authors2) -> authors2.getAge()- author1.getAge()).forEach(author -> System.out.println(author.getAge()));

        authors.stream().distinct().sorted(Comparator.comparingInt(Author::getAge)).forEach(author -> System.out.println(author.getAge()));
    }

    /**
     * 限制条数
     */
    public void limit() {
        //打印所有作家的姓名，并且要求其中不能有重复元素。
        List<Author> authors = getAuthors();
        authors.stream().limit(2).forEach(author -> System.out.println(author.getName()));
    }
    /**
     * map转换和计算操作用法
     */
    public void map() {
        //打印所有作家的姓名
        List<Author> authors = getAuthors();
        //写法1
        authors.stream().forEach(author -> System.out.println(author.getName()));
        //写法2
        authors.stream().map(author -> author.getName()).forEach(s -> System.out.println(s));


        //打印所有作家的年龄，并且每个人加一岁
        //写法1
        authors.stream().map(author -> author.getAge() + 1).forEach(age -> System.out.println(age));
        //写法2
        authors.stream().map(author -> author.getAge()).map(age -> age + 2).forEach(age -> System.out.println(age));
    }

    /**
     * flatMap可以把一个对象转换成多个对象作为流中的元素
     */
    public void flatmap() {
        //打印所有书籍的名字。要求对重复的元素进行去重
        List<Author> authors = getAuthors();
        authors.stream().flatMap(author -> author.getBooks().stream()).distinct().forEach(book -> System.out.println(book.getName()));
        System.out.println("===================================");
        //打印所有书籍的分类。不能出现这种格式：哲学,爱情，要分成两个类。
        authors.stream().flatMap(author -> author.getBooks().stream())
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(s -> System.out.println(s));
    }

    /**
     * map和flatmap的区别，举例感受
     * 如果想要获取List<Book>的形式，flatmap表现非常好，而map则很复杂
     * 如果要对book去重，就更麻烦了
     */
    public void differenceBetweenMapAndFlatmap(){
        //打印所有书籍的名字。要求对重复的元素进行去重
        List<Author> authors = getAuthors();
        List<List<Book>> collect = authors.stream().map(author -> author.getBooks()).collect(Collectors.toList());
        List<Book> books1 = new ArrayList<>();
        collect.stream().forEach(books -> books1.addAll(books));
        System.out.println(books1);

        System.out.println("------------------------------------------");

        //用flatmap，很简单
        List<Book> books2 = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().collect(Collectors.toList());
        System.out.println(books2);

    }

    public static void main(String[] args) {
        中间操作 中间操作 = new 中间操作();
//        中间操作.filter();
//        中间操作.map();
//        中间操作.distinct();
//        中间操作.sorted();
//        中间操作.limit();
//        中间操作.flatmap();
        中间操作.differenceBetweenMapAndFlatmap();
    }

}
